package com.smac.demo.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;


/**
 * 日期时间处理类
 */
@Slf4j
public class DateUtils {

    public static final String FORMAT_DEFAULT = "yyyy-MM-dd";
    public static final String FORMAT_DEFAULT_2 = "yyyyMMdd";
    public static final String FORMAT_ALL = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_ALL_L = "yyyy-MM-dd HH:mm";
    public static final String FORMAT_DATE_MONTH_DAY = "MM-dd";
    public static final String FORMAT_DATE_MONTH_DAY_SHORT = "M.d";
    public static final String FORMAT_TIME_HOUR_MINUTE = "HH:mm";
    public static final String FORMAT_TIME_HOUR_MINUTE_SECOND = "HH:mm:ss";
    public static final String FORMAT_MONTH_DAY = "MM月dd日";

    public static DateTimeFormatter FORMATTER_DEFAULT = DateTimeFormat.forPattern(FORMAT_DEFAULT);
    public static DateTimeFormatter FORMATTER_DEFAULT_2 = DateTimeFormat.forPattern(FORMAT_DEFAULT_2);
    public static DateTimeFormatter FORMATTER_DEFAULT_ALL = DateTimeFormat.forPattern(FORMAT_ALL);
    public static DateTimeFormatter FORMATTER_DEFAULT_ALL_L = DateTimeFormat.forPattern(FORMAT_ALL_L);
    public static DateTimeFormatter FORMATTER_DEF_MONTH_DAY = DateTimeFormat.forPattern(FORMAT_DATE_MONTH_DAY);
    public static DateTimeFormatter FORMATTER_SHORT_MONTH_DAY = DateTimeFormat.forPattern(FORMAT_DATE_MONTH_DAY_SHORT);
    public static DateTimeFormatter FORMATTER_TIME_HOUR_MINUTE = DateTimeFormat.forPattern(FORMAT_TIME_HOUR_MINUTE);
    public static DateTimeFormatter FORMATTER_TIME_HOUR_MINUTE_SECOND = DateTimeFormat.forPattern(FORMAT_TIME_HOUR_MINUTE_SECOND);

    private static String[] weekDays = {"周一", "周二", "周三", "周四", "周五", "周六","周日"};

    /**
     * 得到时间的差值
     * @param startDate yyyy-MM-dd
     * @param startTime
     * @param endDate yyyy-MM-dd
     * @param endTime
     * @param formart  JodaDateUtils 中的格式
     * @return  1h20m
     */
    public static String getSubtractTime(String startDate,String startTime,String endDate,String endTime,String formart){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formart);
        DateTime startDateTime = null;
        DateTime endDateTime = null;
        Date startParse = null;
        Date endParse = null;
        String subtractTime = "";
        try {
            startParse = simpleDateFormat.parse(startDate + " " + startTime);
            endParse = simpleDateFormat.parse(endDate + " " + endTime);
            startDateTime =new DateTime(startParse);
            endDateTime = new DateTime(endParse);
        } catch (ParseException e) {
            log.error("日期转换出现错误,",e);
            return  null;
        }
        if(startParse==null || endParse==null  || startDateTime.compareTo(endDateTime)>=0){
            return null;
        }
        Period period = new Period(startDateTime,endDateTime);
        int hours = 0;
        int minutes = 0;
        if(period.getDays()>0){
            hours = period.getDays() *  24;
        }
        if(period.getHours()>0){
            hours  = hours + period.getHours();
        }
        if(period.getMinutes()>0){
            minutes = period.getMinutes();
        }
        if(hours>0){
            subtractTime = hours+"h";
        }
        if(minutes>0){
            subtractTime = subtractTime+minutes+"m";
        }
        return subtractTime;
    }

    /**
     * 得到时间的差值 分钟
     * @param startDate yyyy-MM-dd
     * @param startTime
     * @param endDate yyyy-MM-dd
     * @param endTime
     * @param formart  JodaDateUtils 中的格式
     * @return
     */
    public static int getSubtractTimeMunite(String startDate,String startTime,String endDate,String endTime,String formart){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formart);
        DateTime startDateTime = null;
        DateTime endDateTime = null;
        Date startParse = null;
        Date endParse = null;
        int  subtractTimeMinute = 0;
        try {
            startParse = simpleDateFormat.parse(startDate + " " + startTime);
            endParse = simpleDateFormat.parse(endDate + " " + endTime);
            startDateTime =new DateTime(startParse);
            endDateTime = new DateTime(endParse);
        } catch (ParseException e) {
            log.error("日期转换出现错误,",e);
            return  0;
        }
        if(startParse==null || endParse==null  || startDateTime.compareTo(endDateTime)>=0){
            return 0;
        }
        Period period = new Period(startDateTime,endDateTime);
        int hours = 0;
        int minutes = 0;
        if(period.getDays()>0){
            hours = period.getDays() *  24;
        }
        if(period.getHours()>0){
            hours  = hours + period.getHours();
        }
        if(period.getMinutes()>0){
            minutes = period.getMinutes();
        }
        if(hours>0){
            subtractTimeMinute = hours*60;
        }
        if(minutes>0){
            subtractTimeMinute = subtractTimeMinute + minutes;
        }
        return subtractTimeMinute;
    }


    /**
     *
     * @param startDate
     * @param endDate
     * @param currentDate
     * @return
     */
    public static boolean betweenDays(String startDate, String endDate, String currentDate){
        if(StringUtils.isBlank(startDate)
                || StringUtils.isBlank(endDate)
                || StringUtils.isBlank(currentDate)){
            return false;
        }
        return compareDate(currentDate, startDate, FORMAT_DEFAULT) && compareDate(endDate, currentDate, FORMAT_DEFAULT);
    }


    /**
     * 获取日期的星期
     * @param dateStr
     * @return
     */
    public static String getWeekOfDate(String dateStr, String pattern) {
        Date dt = parseDate(dateStr, pattern);
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0){
            w = 0;
        }
        return weekDays[w];
    }


    /**
     * 计算两个字符串表示的时间相差的分钟数
     * @param startDate
     * @param endDate
     * @param format 日期时间格式
     * @return
     */
    public static long getIntervalInMinutes(String startDate,String endDate,String format){
        Date bDate = parseDate(startDate,format);
        Date eDate = parseDate(endDate, format);
        Calendar d1 = new GregorianCalendar();
        d1.setTime(bDate);
        Calendar d2 = new GregorianCalendar();
        d2.setTime(eDate);
        long ei = d2.getTimeInMillis() - d1.getTimeInMillis();
        long minutes = ei /(1000 * 60);
        return minutes;
    }


    /**
     * 日期比较，较晚的日期大
     * @param date1
     * @param date2
     * @param dateFormet
     * @return
     */
    public static boolean compareDate(String date1, String date2, String dateFormet){
        SimpleDateFormat format = new SimpleDateFormat(dateFormet, Locale.CHINA);
        Date d1;
        Date d2;
        try {
            d1 = format.parse(date1);
            d2 = format.parse(date2);
        } catch (ParseException e) {
            return true;
        }
        return d2.before(d1);
    }

    /**
     * 将指定的字符串转化成Date对象
     * @param dateStr
     * @param pattern
     * @return
     */
    public static Date parseDate(String dateStr,String pattern){
        if(StringUtils.isBlank(dateStr) || StringUtils.isBlank(pattern)){
            return null;
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(pattern);
        return dateTimeFormatter.parseDateTime(dateStr).toDate();
    }

    /**
     * 获取当前日期是周几<br>
     *
     * @param dt
     * @return 当前日期是周几
     */
    public static String getWeekOfDate(Date dt) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0){
            w = 0;
        }
        return weekDays[w];
    }

    public static String getWeekOfDate(String dateStr) {
        return getWeekOfDate(dateStr, FORMAT_DEFAULT);
    }

    public static DateTime parseDateTime(String dateStr, DateTimeFormatter formatter) {
        if (formatter == null || StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            return formatter.parseDateTime(dateStr);
        } catch (Exception e) {
            log.error("转换日期出错", e);
        }
        return null;
    }

    public static int compareTime(String beforeTime, String afterTime) {// 18:00,19:00
        if (beforeTime.length() < 6 && afterTime.length() < 6) {
            int btime = Integer.parseInt(beforeTime.split(":")[0]);
            int etime = Integer.parseInt(afterTime.split(":")[0]);
            if (btime >= etime) {
                return 1;
            } else {
                return 0;
            }
        }
        return -1;
    }

    /**
     * 为指定的日期增加指定的天数
     *
     * @param date
     * @param day
     * @return
     */
    public static Date addDays(Date date, int day) {
        DateTime dateTime = new DateTime(date);
        dateTime = dateTime.plusDays(day);
        return dateTime.toDate();
    }

    /**
     * 为指定的日期增加指定的小时数
     *
     * @param date
     * @param i
     * @return
     */
    public static Date addHours(Date date, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, i);
        return calendar.getTime();
    }


    /**
     * 将传入的日期增加指定天数
     *
     * @param dateStr
     * @param day
     * @param pattern
     * @return
     */
    public static String addDays(String dateStr, int day, String pattern) {
        Date date = parseDate(dateStr, pattern);
        date = addDays(date, day);
        return formatDate(date, pattern);
    }

    /**
     * 格式化日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        DateTime dateTime = new DateTime(date);
        return dateTime.toString(pattern);
    }


    /**
     * 从指定格式转换成另一个格式
     * @return 如果出错，原样返回
     */
    public static String fromatTo(String dateStr,DateTimeFormatter fromFormatter,DateTimeFormatter toFormatter) {
        DateTime dateTime = parseDateTime(dateStr, fromFormatter);
        if (dateTime == null) {
            return dateStr;
        }
        return dateTime.toString(toFormatter);
    }

    /**
     * 获取当前格式化后的当前时间
     * @param format
     * @return
     */
    public static String now(DateTimeFormatter format) {
        return DateTime.now().toString(format);
    }


    /**
     * 日期字符串是否在开始和结束日期范围内
     *
     * @param beginDate yyyy-mm-dd
     * @param endDate
     * @param dateStr
     * @return
     */
    private static boolean dateBetween(DateTime beginDate, DateTime endDate, String dateStr, DateTimeFormatter dateTimeFormatter) {
        Interval i = new Interval(beginDate, endDate);
        return i.contains(parseDateTime(dateStr, dateTimeFormatter));
    }


    public static String now(String formatDefault) {
        return formatDate(new Date(),formatDefault);
    }

    /**
     * 获取start到end的天数
     * @param start
     * @param end
     * @param formatterDefault
     * @return
     */
    public static int getDaysBetween(String start, String end, DateTimeFormatter formatterDefault) {
        DateTime startDt = parseDateTime(start, formatterDefault);
        DateTime endDt = parseDateTime(end, formatterDefault);
        return Days.daysBetween(startDt, endDt).getDays();
    }


    public static String addYears(String dateStr, int year, String pattern) {
        try {
            DateFormat format1 = new SimpleDateFormat(pattern);
            Date date = format1.parse(dateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.YEAR, year);
            return format1.format(cal.getTime());
        } catch (ParseException e) {
            log.error("日期解析出错",e);
        }
        return null;
    }


    public static String transDateToChinese(String date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Calendar c = Calendar.getInstance();
            Date d = format.parse(date);
            c.setTime(d);
            return (c.get(Calendar.MONTH)+1)+"月"+c.get(Calendar.DATE)+"日";
        } catch (ParseException e) {
            log.error("日期解析出错",e);
            return "";
        }
    }


    public static long getInetvalDays(String goDate, String backDate){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date go;
        Date back;
        try {
            go = format.parse(goDate);
            back = format.parse(backDate);
        } catch (ParseException e) {
            return 0;
        }

        return (back.getTime() - go.getTime())/(24*60*60*1000);
    }


    /**
     * 分钟数转为n小时m分
     * @param time
     * @return
     */
    public static String parseMinutes(int time){
        int minutes = time % 60;
        int hours = time / 60;
        StringBuilder sb = new StringBuilder();
        if(hours != 0){
            sb.append(hours).append("小时");
        }
        if(minutes != 0){
            sb.append(minutes).append("分");
        }
        return sb.toString();

    }


}
